/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bff.designtime.generator.changeconvertor.methodgenerator;

import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bff.designtime.generator.changeconvertor.FSChangeConvertorGenContext;
import com.inspur.edp.bff.designtime.generator.common.GenUtils;
import com.inspur.edp.bff.designtime.generator.common.MetadataInfo;
import com.inspur.edp.bff.designtime.generator.udt.UdtInfo;
import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.utils.ExpressionUtils;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.changeset.ValueObjModifyChangeDetail;
import com.inspur.edp.cef.generator.DotNetToJavaStringHelper;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import lombok.var;
import org.eclipse.jdt.core.dom.*;
import java.util.ArrayList;
import java.util.Arrays;

public class ConvertModifyPropertiesFormVoGenerator extends ClassMethodGenerator {

    private static final String ParamVmElementCode = "vmElementCode";
    private static final String ParamVmValue = "vmValue";
    private static final String ParamBeChange = "beChange";
    private static final String ParamBeValue = "beValue";
    private FSChangeConvertorGenContext changeConvertorContext;

    public ConvertModifyPropertiesFormVoGenerator(
        FSChangeConvertorGenContext changeConvertorContext) {
        this.changeConvertorContext = changeConvertorContext;
    }


    // region MethodBody
    @Override
    protected Block buildMethodBody() {
        Statement beValueStatement = getBEValueDeclaration();
        SwitchStatement result = getSwitchBlock();
        for (IGspCommonField gspCommonField : changeConvertorContext.getVmObject().getContainElements()) {
            GspViewModelElement item = (GspViewModelElement) gspCommonField;
            if (item.getIsVirtual()) {
                continue;
            }
            if (DotNetToJavaStringHelper.isNullOrEmpty(item.getMapping().getTargetObjId())) {
                throw new RuntimeException(
                    "#GspBefError# 字段" + item.getCode() + " 的Mapping字段ID不允许为空#GspBefError#");
            }

            if (item.getMapping().getTargetMetadataId() .equals(changeConvertorContext.getVmGeneratorContext()
                .getVm().getMapping().getTargetMetadataId()) == false) {
                continue;
            }

            Object tempVar = changeConvertorContext.getBeObject().findElement(item.getMapping().getTargetObjId());
            GspBizEntityElement entityElement = (GspBizEntityElement) (
                (tempVar instanceof GspBizEntityElement) ? tempVar : null);
            if (entityElement == null) {
                continue;
            }
            addElementMapBlock(item, entityElement, result);
        }
        Block block = ast.newBlock();
        block.statements().add(beValueStatement);
        block.statements().add(result);
        return block;
    }

    private SwitchCase getSwitchCase(String value) {
        StringLiteral caseValue = ast.newStringLiteral();
        caseValue.setLiteralValue(value);
        SwitchCase caseStatement = ast.newSwitchCase();
        caseStatement.setExpression(caseValue);

        return caseStatement;
    }

//    private void addCase(java.util.ArrayList<StatementSyntax> statements,
//                         GspViewModelElement vmElement, RefObject<SwitchStatementSyntax> result) {
//        result.argvalue = result.argvalue.AddSections(SyntaxFactory.SwitchSection().WithLabels(
//                SyntaxFactory.<SwitchLabelSyntax>SingletonList(SyntaxFactory.CaseSwitchLabel(SyntaxFactory
//                        .LiteralExpression(SyntaxKind.StringLiteralExpression,
//                                SyntaxFactory.Literal(vmElement.LabelID)))))
//                .WithStatements(SyntaxFactory.List(statements.toArray(new StatementSyntax[]{}))));
//    }

    // object beValue =null;
    private Statement getBEValueDeclaration() {
        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName(ParamBeValue));
        frag.setInitializer(ast.newNullLiteral());
        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        statement.setType(ast.newSimpleType(ast.newSimpleName("Object")));
        return statement;
    }

    private SwitchStatement getSwitchBlock() {
        SwitchStatement statement = ast.newSwitchStatement();
        statement.setExpression(ast.newSimpleName(ParamVmElementCode));
        return statement;
    }

    // region AddElementMapBlock
    private void addElementMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement, SwitchStatement result) {
        if (vmElement.getIsUdt()) {
            addUdtMapBlock(vmElement, beElement, result);
            return;
        }
        switch (vmElement.getObjectType()) {
            case None:
            case DynamicProp:
                addBasicElementMapBlock(vmElement, beElement, ParamVmValue, result);
                break;
            case Association:
                addAssElementMapBlock(vmElement, beElement, result);
                break;
            case Enum:
                addEnumElementMapBlock(vmElement, beElement, result);
                break;
            default:
                throw new RuntimeException(
                    "#GspBefError# 错误的类型" + vmElement.getObjectType().toString()
                        + " #GspBefError# ");
        }
    }

    private void addUdtMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement,
        SwitchStatement result) {
        if (vmElement.getHasAssociation() && vmElement.containRefElementNotFromAssoUdt()) {
            addAssoUdtMapBlock(vmElement, beElement, result);
        } else {
            addBasicElementMapBlock(vmElement, beElement, ParamVmValue, result);
        }
    }

    private ExpressionStatement addChange(String change, String key, String valueName,
        boolean isKeyPro) {

        MethodInvocation changeInvocation = ExpressionUtils.getMethodInvocation(ast, change, "getPropertyChanges");
        MethodInvocation invocation = ExpressionUtils.getMethodInvocation(ast, changeInvocation, "put");

        Expression keyArgument;
        if (isKeyPro) {
            keyArgument = ast.newSimpleName(key);
        } else {
            StringLiteral literal = ast.newStringLiteral();
            literal.setLiteralValue(key);
            keyArgument = literal;
        }

        invocation.arguments().add(keyArgument);
        invocation.arguments().add(ast.newSimpleName(valueName));

        return ast.newExpressionStatement(invocation);
    }

    //ValueObjModifyChangeDetail beValueObjModifyChangeDetail = new ValueObjModifyChangeDetail();
    //string key = vmValue.PropertyChanges.FirstOrDefault().Key;
    //var value = vmValue.PropertyChanges.FirstOrDefault().Value as VoDepartmentInfo;
    //BeDepartmentInfo value2 = new BeDepartmentInfo(value);
    //value2.enumTest2 = value.enumTest2;
    //beChange.PropertyChanges.Add("Department", beValueObjModifyChangeDetail);
    private void addAssoUdtMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement, SwitchStatement result) {
        result.statements().add(getSwitchCase(vmElement.getLabelID()));

        String vmChangeName = "vo" + vmElement.getLabelID() + "Change";
        result.statements().add(getVmChangeStatement(vmChangeName));

        String beChangeName = beElement.getLabelID() + "Change";
        result.statements().add(createChangeStatement(beChangeName));

        String udtInfoVarName = vmElement.getLabelID() + "UdtInfo";
        String udtKeyVarName = vmElement.getLabelID() + "UdtKey";

        result.statements().add(getUdtKeyStatement(vmElement, udtKeyVarName, vmChangeName));
        result.statements().add(getUdtInfoStatement(vmElement, udtInfoVarName, vmChangeName, udtKeyVarName));

        String beInfoName = vmElement.getLabelID() + "BeInfo";
        result.statements().add(getCreateBeInfoStatement(vmElement, beElement, beInfoName, udtInfoVarName));


        for (IGspCommonField gspCommonField : vmElement.getChildAssociations().get(0).getRefElementCollection()) {
            GspViewModelElement refElement = (GspViewModelElement) gspCommonField;
            //TODO 后续支持带出字段是关联
            if (refElement.getIsFromAssoUdt() || refElement.getObjectType() == GspElementObjectType.Association
                || refElement.getObjectType() == GspElementObjectType.DynamicProp) {
                continue;
            }
            GspBizEntityElement beRefElement = findBeRefElement(beElement, refElement);
            result.statements().add(buildNotUdtRefStatement(refElement, beRefElement, beInfoName, udtInfoVarName));
        }

        result.statements().add(addChange(beChangeName, udtKeyVarName, beInfoName, true));
        result.statements().add(addChange(ParamBeChange, beElement.getLabelID(), beChangeName,false));

        result.statements().add(ast.newBreakStatement());
    }

    private Statement getVmChangeStatement(String vmChangeName) {


        TypeInfo typeInfo = new TypeInfo(ValueObjModifyChangeDetail.class);
        Type type = typeInfo.getType(ast,changeConvertorContext.getVmGeneratorContext().getEntityContext());
        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName(vmChangeName));
        CastExpression castExpression = ast.newCastExpression();
        castExpression.setExpression(ast.newSimpleName(ParamVmValue));
        castExpression.setType(type);
        frag.setInitializer(castExpression);

        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        Type type1 = typeInfo.getType(ast,changeConvertorContext.getVmGeneratorContext().getEntityContext());
        statement.setType(type1);

        return statement;
    }

    private GspBizEntityElement findBeRefElement(GspBizEntityElement beElement,GspViewModelElement voRefElement) {

        for (IGspCommonField refElement : beElement.getChildAssociations().get(0).getRefElementCollection()) {
            if (refElement.getID() .equals( voRefElement.getMapping().getTargetElementId())) {
                return (GspBizEntityElement) ((refElement instanceof GspBizEntityElement) ? refElement
                    : null);
            }
        }

        return null;
    }

    private Statement createChangeStatement(String beChangeName) {

        Type type = new TypeInfo(ValueObjModifyChangeDetail.class).getType(ast, changeConvertorContext.getEntityGenContext());
        //ast.newSimpleType(ast.newSimpleName("ValueObjModifyChangeDetail"));
        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName(beChangeName));
        ClassInstanceCreation creation = ast.newClassInstanceCreation();
        creation.setType(type);
        frag.setInitializer(creation);
        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        Type type1 = new TypeInfo(ValueObjModifyChangeDetail.class).getType(ast, changeConvertorContext.getEntityGenContext());
        statement.setType(type1);
        return statement;
    }

    private Statement getUdtKeyStatement(GspViewModelElement vmElement,
        String udtInfoVarName,
        String changeVarName) {
        MethodInvocation initer = ExpressionUtils.getMethodInvocation(ast, changeVarName, "getPropertyChanges");
        initer = ExpressionUtils.getMethodInvocation(ast, initer, "keySet");
        initer = ExpressionUtils.getMethodInvocation(ast, initer, "stream");
        initer = ExpressionUtils.getMethodInvocation(ast,initer, "findFirst");
        initer = ExpressionUtils.getMethodInvocation(ast, initer, "get");

        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setInitializer(initer);
        frag.setName(ast.newSimpleName(udtInfoVarName));

        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        statement.setType(ast.newSimpleType(ast.newSimpleName("String")));
        return statement;
    }

    private Statement getUdtInfoStatement(GspViewModelElement vmElement,
        String udtInfoVarName,
        String changeVarName,
        String udtKeyVarName) {

        String asspType = vmElement.getAssociationTypeName();

        MethodInvocation initer = ExpressionUtils.getMethodInvocation(ast, changeVarName, "getPropertyChanges");
        initer = ExpressionUtils.getMethodInvocation(ast, initer, "get");
        initer.arguments().add(ast.newSimpleName(udtKeyVarName));
        CastExpression castExpression = ast.newCastExpression();
        castExpression.setExpression(initer);
        castExpression.setType(ast.newSimpleType(ast.newSimpleName(asspType)));


        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setInitializer(castExpression);
        frag.setName(ast.newSimpleName(udtInfoVarName));

        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        statement.setType(ast.newSimpleType(ast.newSimpleName(asspType)));
        return statement;
    }

    private Statement getCreateBeInfoStatement(GspViewModelElement vmElement,
        GspBizEntityElement beElement,
        String beInfoVarName,
        String udtInfoVarName) {

        String assoClassName = null;
        TypeInfo assoTypeInfo = GenUtils.GetBEAssoType(changeConvertorContext.getVmGeneratorContext(), beElement, assoClassName);

        Type typeSyntax = ast.newSimpleType(ast.newQualifiedName(
            ast.newName(assoTypeInfo.getTypePackageName()),
            ast.newSimpleName(assoTypeInfo.getTypeName())));

        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName(beInfoVarName));
        ClassInstanceCreation creation = ast.newClassInstanceCreation();
        creation.setType(typeSyntax);
        creation.arguments().add(ast.newSimpleName(udtInfoVarName));

        frag.setInitializer(creation);

        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        Type typeSyntax1 = ast.newSimpleType(ast.newQualifiedName(
            ast.newName(assoTypeInfo.getTypePackageName()),
            ast.newSimpleName(assoTypeInfo.getTypeName())));
        statement.setType(typeSyntax1);
        return statement;
    }

    private Statement buildNotUdtRefStatement(GspViewModelElement vmElement,
        GspBizEntityElement beElement,
        String beInfoVarName,
        String udtInfoVarName) {


        MethodInvocation rightMember = ExpressionUtils
            .getMethodInvocation(ast, udtInfoVarName, "get" + vmElement.getLabelID());
        MethodInvocation leftMember = ExpressionUtils
            .getMethodInvocation(ast, beInfoVarName, "set" + beElement.getLabelID());


        if (vmElement.getIsUdt()) {
            IfStatement ifStatement = ast.newIfStatement();
            TypeInfo udtType = getUdtType(vmElement.getUdtPkgName(), vmElement.getUdtID());

            MethodInvocation copyExpression = ExpressionUtils.getMethodInvocation(ast, rightMember, "copy");

            CastExpression castExpression = ast.newCastExpression();
            castExpression.setExpression(copyExpression);
            castExpression.setType(ast.newSimpleType(
                ast.newQualifiedName(
                    ast.newName(udtType.getTypePackageName()),
                    ast.newSimpleName(udtType.getTypeName())
                )
            ));
            leftMember.arguments().add(castExpression);

            InfixExpression infix =ast.newInfixExpression();
            infix.setLeftOperand(ExpressionUtils
                .getMethodInvocation(ast, udtInfoVarName, "get" + vmElement.getLabelID()));
            infix.setOperator(InfixExpression.Operator.NOT_EQUALS);
            infix.setRightOperand(ast.newNullLiteral());
            ifStatement.setExpression(infix);
            Block thenBlock  =ast.newBlock();
            thenBlock.statements().add(ast.newExpressionStatement(leftMember));
            ifStatement.setThenStatement(thenBlock);
            return ifStatement;
        }

        leftMember.arguments().add(rightMember);
        return ast.newExpressionStatement(leftMember);
    }

    private TypeInfo getUdtType(String packageName, String udtId) {
        UdtInfo udtInfo = changeConvertorContext.getVmGeneratorContext().getUdtInfo(udtId, packageName);
        return udtInfo.getUdtType();
    }

    private void addBasicElementMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement,
        String valueName, SwitchStatement result) {
        SwitchCase caseStatement = getSwitchCase(vmElement.getLabelID());

        result.statements().add(caseStatement);
        result.statements().add(addChange(ParamBeChange, beElement.getLabelID(), valueName, false));
        result.statements().add(ast.newBreakStatement());
    }

    // region AddAssElementMapBlock
    private void addAssElementMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement, SwitchStatement result) {

        result.statements().add(getSwitchCase(vmElement.getLabelID()));


        result.statements().add(getIfNullStatement(beElement, vmElement));
        result.statements().add(getAddValueStatement(beElement));

        result.statements().add(ast.newBreakStatement());
//        AddCase(statementSyntax, vmElement, result);

    }


    // region GetIfNullStatement
    private Statement getIfNullStatement(GspBizEntityElement beElement, GspViewModelElement vmElement) {

        IfStatement ifStatement = ast.newIfStatement();
        InfixExpression condition = ast.newInfixExpression();
        condition.setLeftOperand(ast.newSimpleName(ParamVmValue));
        condition.setRightOperand(ast.newNullLiteral());
        condition.setOperator(InfixExpression.Operator.EQUALS);
        ifStatement.setExpression(condition);

        Block thenBlock = ast.newBlock();
        Assignment thenInvocation = ast.newAssignment();
        thenInvocation.setLeftHandSide(ast.newSimpleName(ParamBeValue));
        thenInvocation.setRightHandSide(ast.newNullLiteral());
        thenBlock.statements().add(ast.newExpressionStatement(thenInvocation));

        ifStatement.setThenStatement(thenBlock);

        Block elseblock = getElseStatements(beElement, vmElement);
        ifStatement.setElseStatement(elseblock);

        return ifStatement;

    }


    // region GetElseStatements
    private Block getElseStatements(GspBizEntityElement beElement, GspViewModelElement vmElement) {

        Block elseBlock = ast.newBlock();

        addGetVMAssStatement(elseBlock, beElement, vmElement);
        newBEAssStatement(elseBlock, beElement, vmElement);
        assPropMapBlock(vmElement, beElement, elseBlock);
        setBEValueStatement(elseBlock);
//        elseStatements.add(getAddStatement(beElement));
//        return elseStatements.toArray(new StatementSyntax[]{});
        return elseBlock;
    }

    private void addGetVMAssStatement(Block block, GspBizEntityElement beElement, GspViewModelElement vmElement) {
        String vmAssoTypeName = vmElement.getAssociationTypeName();

        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName("vmAss"));
        CastExpression castExpression = ast.newCastExpression();
        castExpression.setExpression(ast.newSimpleName(ParamVmValue));
        castExpression.setType(ast.newSimpleType(ast.newSimpleName(vmAssoTypeName)));
        frag.setInitializer(castExpression);

        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        statement.setType(ast.newSimpleType(ast.newSimpleName(vmAssoTypeName)));

        block.statements().add(statement);
    }


    private void newBEAssStatement(Block elseBlock, GspBizEntityElement beElement, GspViewModelElement vmElement) {
        String associatTypeName = null;
        TypeInfo assType = GenUtils
            .GetBEAssoType(changeConvertorContext.getVmGeneratorContext(), beElement,
                associatTypeName);

        SimpleType type =
            ast.newSimpleType(ast.newQualifiedName(ast.newName(assType.getTypePackageName()),
                ast.newSimpleName(assType.getTypeName())));

        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName("beAss"));
        ClassInstanceCreation creation = ast.newClassInstanceCreation();
        creation.setType(type);
        frag.setInitializer(creation);
        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        SimpleType type1 =
            ast.newSimpleType(ast.newQualifiedName(ast.newName(assType.getTypePackageName()),
                ast.newSimpleName(assType.getTypeName())));
        statement.setType(type1);

        elseBlock.statements().add(statement);
    }

    private void assPropMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement, Block elseBlock) {

        for (IGspCommonField gspCommonField : vmElement.getChildAssociations().get(0).getRefElementCollection()) {
            GspViewModelElement item = (GspViewModelElement) gspCommonField;
            GspBizEntityElement beAssElement = (GspBizEntityElement) (
                (beElement.getChildAssociations().get(0).getRefElementCollection()
                    .getItem(item.getMapping().getTargetObjId())
                    instanceof GspBizEntityElement)
                    ? beElement.getChildAssociations().get(0).getRefElementCollection()
                    .getItem(item.getMapping().getTargetObjId())
                    : null);

            MethodInvocation beData = ExpressionUtils.getMethodInvocation(ast, "beAss", "set" + beAssElement.getLabelID());
            MethodInvocation voData = ExpressionUtils.getMethodInvocation(ast, "vmAss", "get" + item.getLabelID());
            beData.arguments().add(voData);
            elseBlock.statements().add(ast.newExpressionStatement(beData));
        }

        MethodInvocation beData = ExpressionUtils.getMethodInvocation(ast, "beAss", "set" + beElement.getLabelID());
        MethodInvocation voData = ExpressionUtils.getMethodInvocation(ast, "vmAss", "get" + vmElement.getLabelID());
        beData.arguments().add(voData);
        elseBlock.statements().add(ast.newExpressionStatement(beData));
    }

    private void setBEValueStatement(Block elseBlock) {
        Assignment assignment = ast.newAssignment();
        assignment.setLeftHandSide(ast.newSimpleName(ParamBeValue));
        assignment.setRightHandSide(ast.newSimpleName("beAss"));
        elseBlock.statements().add(ast.newExpressionStatement(assignment));
//        assignment.setOperator(Assignment.Operator.ASSIGN);
    }

    ///#endregion GetElseStatements

    ///#endregion GetIfNullStatement

    private ExpressionStatement getAddValueStatement(GspBizEntityElement beElement) {
        MethodInvocation changeInvocation = ExpressionUtils.getMethodInvocation(ast, ParamBeChange, "getPropertyChanges");
        MethodInvocation invocation = ExpressionUtils.getMethodInvocation(ast, changeInvocation, "put");

        StringLiteral literal = ast.newStringLiteral();
        literal.setLiteralValue(beElement.getLabelID());
        invocation.arguments().add(literal);
        invocation.arguments().add(ast.newSimpleName(ParamBeValue));

        return ast.newExpressionStatement(invocation);
    }

    // endregion AddAssElementMapBlock
    private void addEnumElementMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement, SwitchStatement result) {
        String enumClassName = null;
        TypeInfo enumType = GenUtils
            .getBeEnumType(changeConvertorContext.getVmGeneratorContext(), beElement,
                enumClassName);

        String varName = "vmEnumValue" + vmElement.getLabelID();

        result.statements().add(getSwitchCase(vmElement.getLabelID()));
        result.statements().add(getEnumValueStatement(vmElement, varName));
        result.statements().add(addEnumChange(beElement, varName, enumClassName, enumType));
        result.statements().add(ast.newBreakStatement());

    }

    private Statement getEnumValueStatement(GspViewModelElement vmElement, String varName) {
        String enumType = vmElement.getEnumTypeName();

        VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
        frag.setName(ast.newSimpleName(varName));

        CastExpression castExpression = ast.newCastExpression();
        castExpression.setType(ast.newSimpleType(ast.newSimpleName(enumType)));
        castExpression.setExpression(ast.newSimpleName(ParamVmValue));
        frag.setInitializer(castExpression);

        VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
        statement.setType(ast.newSimpleType(ast.newSimpleName(enumType)));
        return statement;
    }

    private IfStatement addEnumChange(GspBizEntityElement beElement, String varName, String enumClassName, TypeInfo enumType) {
        IfStatement ifStatement = ast.newIfStatement();
        InfixExpression infixExpression =  ast.newInfixExpression();
        infixExpression.setLeftOperand(ast.newSimpleName(varName));
        infixExpression.setOperator(InfixExpression.Operator.EQUALS);
        infixExpression.setRightOperand(ast.newNullLiteral());
        ifStatement.setExpression(infixExpression);




        MethodInvocation changeInvocation1 = ExpressionUtils.getMethodInvocation(ast, ParamBeChange, "getPropertyChanges");
        Block thenBlock = ast.newBlock();
        MethodInvocation thenMtheod = ast.newMethodInvocation();
        thenMtheod.setExpression(changeInvocation1);
        thenMtheod.setName(ast.newSimpleName("put"));
        StringLiteral stringLiteral = ast.newStringLiteral();
        stringLiteral.setLiteralValue(beElement.getLabelID());
        thenMtheod.arguments().add(stringLiteral);
        thenMtheod.arguments().add(ast.newNullLiteral());
        thenBlock.statements().add(ast.newExpressionStatement(thenMtheod));
        ifStatement.setThenStatement(thenBlock);

        MethodInvocation changeInvocation = ExpressionUtils.getMethodInvocation(ast, ParamBeChange, "getPropertyChanges");
        MethodInvocation invocation = ExpressionUtils.getMethodInvocation(ast, changeInvocation, "put");

        StringLiteral literal = ast.newStringLiteral();
        literal.setLiteralValue(beElement.getLabelID());
        invocation.arguments().add(literal);

        ArrayAccess arg = ast.newArrayAccess();
        MethodInvocation array = ast.newMethodInvocation();
        array.setExpression(ast.newQualifiedName(
            ast.newName(enumType.getTypePackageName()), ast.newSimpleName(enumType.getTypeName())));
        array.setName(ast.newSimpleName("values"));
        arg.setArray(array);

        MethodInvocation index = ExpressionUtils.getMethodInvocation(ast, varName, "ordinal");
        arg.setIndex(index);
        invocation.arguments().add(arg);
        Block elseBlock = ast.newBlock();
        elseBlock.statements().add(ast.newExpressionStatement(invocation));
        ifStatement.setElseStatement(elseBlock);

        return ifStatement;
    }

    @Override
    protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
        return new ArrayList<Modifier.ModifierKeyword>(Arrays.asList(
            new Modifier.ModifierKeyword[]{Modifier.ModifierKeyword.PROTECTED_KEYWORD}));
    }

    @Override
    protected boolean getIsOverride() {
        return true;
    }

    @Override
    protected String getMethodName() {
        return "convertModifyPropFromVM";
    }

    @Override
    protected ArrayList<ParameterInfo> getParameterCollection() {
        ParameterInfo paramEleCode = new ParameterInfo();
        paramEleCode.setParamType(new TypeInfo(String.class));
        paramEleCode.setParamName(ParamVmElementCode);
        ParameterInfo paramValue = new ParameterInfo();
        paramValue.setParamType(new TypeInfo(Object.class));
        paramValue.setParamName(ParamVmValue);
        ParameterInfo paramBeChange = new ParameterInfo();
        paramBeChange.setParamType(new TypeInfo(ModifyChangeDetail.class));
        paramBeChange.setParamName(ParamBeChange);
        return new ArrayList<ParameterInfo>(
            Arrays.asList(new ParameterInfo[]{paramEleCode, paramValue, paramBeChange}));
    }

    @Override
    protected TypeInfo getReturnType() {
        return new TypeInfo("void");
    }
}
